iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 28
1

Layout

因為ImageView轉動時,座標系統也會跟著轉動,所以要覆蓋一個透明的View在ImageView上當作座標的參考點

Method

這次要讓唱盤有自己轉動和讓使用者可以轉動唱盤的效果,所以先設置兩個變數,當使用者在操作的時候,唱盤會停止轉動

private var img1_isTouching = false
private var img2_isTouching = false

唱盤自轉

使用AsyncTask讓唱盤自轉,在doInBackground()每50毫秒更新一次畫面,當時用者沒有在操作且MediaPlayer正在撥放時轉動唱盤
.setRotation().rotation可以設置元件的角度,利用.rotation可以得到現在的角度,所以這邊是每次加上18度
另外旋轉的中心預設是左上角,使用.setPivotX().setPivotY()可以設定旋轉的中心點,這邊是這在ImageVIew的中間

object : AsyncTask<Void, Int, Int>() {
    override fun doInBackground(vararg p0: Void?): Int {
        while (true) {
            Thread.sleep(50)
            if (!img1_isTouching && ch1.isPlaying) {
                //啟動onProgressUpdate()
                publishProgress(1)
            }
            if (!img2_isTouching && ch2.isPlaying) 
                //啟動onProgressUpdate()
                publishProgress(2)
            }
        }
        return 0
    }

    override fun onProgressUpdate(vararg values: Int?) {
        super.onProgressUpdate(*values)
        if (values[0] == 1) {
            //將選轉中心設為ImageView的中心
            imageView.setPivotX((imageView.getWidth() / 2).toFloat())
            imageView.setPivotY((imageView.getHeight() / 2).toFloat())
            //每次旋轉18度
            imageView.setRotation(imageView.rotation + 18)
        } else {
            imageView2.setPivotX((imageView2.getWidth() / 2).toFloat())
            imageView2.setPivotY((imageView2.getHeight() / 2).toFloat())
            imageView2.setRotation(imageView2.rotation + 18)
        }
    }
    override fun onPostExecute(result: Int?) {}
}.execute()

顯示時間

使用Thread更新TextView顯示的時間,透過.currentPosition可以得到MediaPlayer的撥放進度(單位是毫秒),另外.duration可以得到MediaPlayer的總長度

private val handler = Handler(Handler.Callback { msg ->
    var t1 = 0
    var t2 = 0
    when (msg.what) {
        1 -> {
            t1 = ch1.currentPosition / 1000
            t2 = ch2.currentPosition / 1000
            tv_ch1.text = String.format("%02d:%02d", t1 / 60, t1 % 60)
            tv_ch2.text = String.format("%02d:%02d", t2 / 60, t2 % 60)
        }
    }
    true
})
Thread(Runnable {
    while (true) {
        Thread.sleep(100)
        val msg = Message()
        msg.what = 1
        handler.sendMessage(msg)
    }
}).start()

轉動唱盤

對覆蓋在ImageView上的View使用OnTouchListener,在OnTouchListener中,event代表使用者在螢幕上的觸控點
當被使用者按下時(ACTION_DOWN),用.y取得當時的y座標,並把img1_isTouching改為true,當手指離開時(ACTION_UP)改為false

var y1 = 0f
view.setOnTouchListener(object : View.OnTouchListener {
    override fun onTouch(view: View?, event: MotionEvent?): Boolean {
        when (event!!.action and MotionEvent.ACTION_MASK) {
            ACTION_DOWN -> {
                y1 = event.y
                img1_isTouching = true
            }
            ACTION_UP -> {
                img1_isTouching = false
            }
        }
        return true
    }
})

當手指移動時(ACTION_MOVE)改變ImageView的角度,並用.seekTo()改變音樂撥放的進度(單位是毫秒)

var y1 = 0f
view.setOnTouchListener(object : View.OnTouchListener {
    override fun onTouch(view: View?, event: MotionEvent?): Boolean {
        when (event!!.action and MotionEvent.ACTION_MASK) {
            ACTION_DOWN -> {
                y1 = event.y
                img1_isTouching = true
            }
            ACTION_MOVE -> {
                //把剛開始的y座標減掉現在手指的y座標
                var y = (y1 - event.y) / (imageView.height) * 10
                imageView.setPivotX((imageView.getWidth() / 2).toFloat())
                imageView.setPivotY((imageView.getHeight() / 2).toFloat())
                //調整角度
                imageView.setRotation(imageView.rotation + y)
                //透過.seekto改變音樂撥放的進度
                //避免出錯 當改變後的值小於0或大於整首個的進度時就不操作
                if (y.toInt() % 10 == 0 && ch1.currentPosition + y.toInt() > 0 && ch1.currentPosition + y.toInt() < ch1.duration) {
                    ch1.seekTo(ch1.currentPosition + y.toInt() * 50)
                }
            }
            ACTION_UP -> {
                img1_isTouching = false
            }
        }
        return true
    }
})

這邊對數值做了一些計算,不過是通靈憑感覺去慢慢改的,所以實際操作起來完全沒有精準度...


實作成果

雖然沒辦法混音,但只是拿來接歌的話滿好用的


上一篇
Day 27 Mixer(MediaPlayer)
下一篇
Day 29 通知(Notification)
系列文
高中生Kotlin實作30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言